package pub.tbc.toolkit.xml;

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import pub.tbc.toolkit.Loops;
import pub.tbc.toolkit.Objs;
import pub.tbc.toolkit.function.BiConsumer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author tbc on 2016/10/21 18:20:54.
 * @update 2016年11月07日 10:23:18
 */
@Slf4j
public final class SimpleXmlUtil {
    private SimpleXmlUtil() {

    }

    /**
     * 将Map转换为简单xml格式（平铺，不含层层嵌套及标签属性等）的字符串
     *
     * @param param .
     * @return xml-String
     * @update 2016年11月07日 10:26:09 - 增加空值过滤
     */
    public static String map2xml(Map<String, Object> param) {
        final StringBuilder sb = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        sb.append("<param>");
        Loops.forEach(param, new BiConsumer<String, Object>() {
            @Override
            public void accept(String k, Object v) {
                // 过滤掉空值
                if (Objs.isEmpty(v)) return;
                sb.append("<").append(k).append(">").append(v).append("</").append(k).append(">");
            }
        });
        sb.append("</param>");
        return sb.toString();
    }

    public static Map<String, Object> xml2map22222(String xml) throws ParserConfigurationException, IOException, SAXException {
        Map<String, Object> map = Maps.newHashMap();
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = builderFactory.newDocumentBuilder();

        /*
         * builder.parse()方法接受一个流，并且使用这个流的内容构建一个Document对象。
         */
        Document document = builder.parse(new ByteArrayInputStream(xml.getBytes()));

        //获取文档的根元素，赋值给rootElement变量
        Element rootElement = document.getDocumentElement();    //<result>节点
        //获取rootElement的所有子节点（不包括属性节点），返回一个NodeList对象
        NodeList childNodes = rootElement.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            //获取childNodes的第i个节点
            Node childNode = childNodes.item(i);
            // 获取此类值用getTextContent()，而不是getNodeValue()
            map.put(childNode.getNodeName(), childNode.getTextContent());
        }
        return map;
    }

    public static Map<String, Object> xml2map(String xml) {
        Map<String, Object> map = Maps.newHashMap();
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = null;
        try {
            builder = builderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            log.error("XML文档构建-解析配置异常：{}", e.getMessage());
            throw new RuntimeException("XML文档构建-解析配置异常：" + e.getMessage(), e);
        }
        /*
         * builder.parse()方法接受一个流，并且使用这个流的内容构建一个Document对象。
         */
        Document document = null;
        try {
            document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
        } catch (SAXException | IOException e) {
            log.error("解析XML文档出现异常： {}", e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }

        //获取文档的根元素，赋值给rootElement变量
        Element rootElement = document.getDocumentElement();    //<result>节点
        //获取rootElement的所有子节点（不包括属性节点），返回一个NodeList对象
        NodeList childNodes = rootElement.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            //获取childNodes的第i个节点
            Node node = childNodes.item(i);

            NodeList childNodeList = node.getChildNodes();
            if (childNodeList.getLength() <= 1)
                // 获取此类值用getTextContent()，而不是getNodeValue()
                map.put(node.getNodeName(), node.getTextContent());
            else {
                for (int j = 0; j < childNodeList.getLength(); j++) {
                    Node childNode = childNodeList.item(j);
                    Map<String, Object> nodeMap = Maps.newHashMap();
                    map.put(childNode.getNodeName(), nodeMap);
                    setMapByNode(childNode, nodeMap);
                }
            }

        }
        return map;
    }

    public static void setMapByNode(Node node, Map<String, Object> map) {
        if (node == null) {
            return;
        }
        NodeList childNodes = node.getChildNodes();
        if (childNodes.getLength() > 1) {
            for (int i = 0; i < childNodes.getLength(); i++) {
                Node childNode = childNodes.item(i);
                Map<String, Object> nodeMap = Maps.newHashMap();
                map.put(childNode.getNodeName(), nodeMap);
                setMapByNode(childNode, nodeMap);
            }
        } else
            map.put(node.getNodeName(), node.getTextContent());

    }




}
